package com.gitee.magic.framework.base.rest;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.gitee.magic.core.exception.ApplicationException;
import com.gitee.magic.core.utils.StringUtils;
import com.gitee.magic.framework.base.constant.Config;
import com.gitee.magic.framework.head.utils.CodecUtils;
import com.gitee.magic.framework.head.utils.IoUtils;

/**
 * @author start
 */
public class HttpClient {
	
	public static void setDefaultHttps() {
		HttpSsl.setDefaultHttps(HttpSsl.HTTPS_PROTOCOL_TLSV12);
	}

	public static HttpURLConnection createGetHttpConnection(String uri) {
		return createGetHttpConnection(uri, new HashMap<>(0));
	}

	public static HttpURLConnection createGetHttpConnection(String uri, Map<String, String> header) {
		return createDefaultHttpConnection(uri,"GET", header);
	}

	public static HttpURLConnection createPostHttpConnection(String uri) {
		return createPostHttpConnection(uri, new HashMap<>(0));
	}
	
	public static HttpURLConnection createPostHttpConnection(String uri, Map<String, String> header) {
		return createDefaultHttpConnection(uri,"POST",header);
	}
	
	public static HttpURLConnection createDefaultHttpConnection(String uri,String method, Map<String, String> header) {
		URL url;
		try {
			url = new URL(uri);
		} catch (MalformedURLException e) {
			throw new ApplicationException(e);
		}
		HttpURLConnection conn;
		try {
			conn = (HttpURLConnection) url.openConnection();
		} catch (IOException e) {
			throw new ApplicationException(e);
		}
		try {
			conn.setRequestMethod(method);
		} catch (ProtocolException e) {
			throw new ApplicationException(e);
		}
		//允许读入
		conn.setDoInput(true);
		//允许写出
		conn.setDoOutput(true);
		//不使用缓存
		conn.setUseCaches(false);
		conn.setInstanceFollowRedirects(true);
		conn.setReadTimeout(30000);
		conn.setConnectTimeout(30000);
		for (String key : header.keySet()) {
			conn.setRequestProperty(key, header.get(key));
		}
		return conn;
	}

	/**
	 * 设置请求主体
	 * @param conn
	 * @param content
	 * @param charsetName
	 */
	public static void setRequestBody(HttpURLConnection conn, String content, String charsetName) {
		DataOutputStream out=null;
		try {
			out = new DataOutputStream(conn.getOutputStream());
			out.write(content.getBytes(charsetName));
			out.flush();
		} catch (IOException e) {
			throw new ApplicationException(e);
		}finally {
			if(out!=null) {
				try {
					out.close();
				} catch (IOException e) {
					throw new ApplicationException(e);
				}
			}
		}
	}
	
	/**
	 * 响应流
	 * 
	 * @param conn
	 * @return
	 */
	public static InputStream result(HttpURLConnection conn) {
		int code=200;
		try {
			if (conn.getResponseCode() == code) {
				return conn.getInputStream();
			} else {
				return conn.getErrorStream();
			}
		} catch (IOException e) {
			throw new ApplicationException(e);
		}
	}

	/**
	 * 响应数据
	 * 
	 * @param conn
	 * @return
	 * @throws IOException
	 */
	public static String result(HttpURLConnection conn, String charsetName) {
		try {
			return new String(IoUtils.inputStreamConvertBytes(result(conn), -1), charsetName);
		} catch (UnsupportedEncodingException e) {
			throw new ApplicationException(e);
		}
	}

	/**
	 * 生成GET URL参数列表
	 * 参数进行URL编码
	 * 
	 * @param params
	 * @return
	 */
	public static String urlQueryString(String url, Map<String, ?> params) {
		String queryString = bodyUrlEncodeString(params);
		String v="?";
		if (url.lastIndexOf(v) != -1) {
			return url + "&" + queryString;
		} else {
			return url + "?" + queryString;
		}
	}
	
	/**
	 * 参数进行URLEncode编码
	 * 
	 * @param params
	 * @return
	 */
	public static String bodyUrlEncodeString(Map<String, ?> params) {
		List<String> lists = new ArrayList<>();
		for (Map.Entry<String, ?> entry : params.entrySet()) {
			Object v=entry.getValue();
			if(v!=null) {
				String value=String.valueOf(v);
				lists.add(entry.getKey() + "=" + CodecUtils.encode(value,Config.getEncoding()));
			}
		}
		return StringUtils.listToString(lists, "&");
	}
	
}
